package PangModel;

import java.awt.*;
import java.util.ArrayList;

/**
 * Created by YILMAZ on 23/4/2015.
 */
public class Ball extends GameObject {
    // adjust the energy constants so that ball will bounce on appropriate height
    // the maximum height a ball will bounce is E/(2*G)

    public static final int BALL_ITEM_INDEX = 1;
    public static final int BALL_BALL_INDEX = 0;

    //Base score points
    public static final int SCORE = 100;

    // E = 2*k/m
    private int BALL_ENERGY_CONSTANT_BIG = 100;
    private int BALL_ENERGY_CONSTANT_MID = 50;
    private int BALL_ENERGY_CONSTANT_SMALL = 30;

    Item itemtoDrop;
    private int size;
   // private int radius;
    private int energy_constant;

    public Ball(int size, int direction, Point coor)
    {
        coordinates = coor;
        if (size == 1) // MAYBE AN ENUMURATION WOULD WORK MUCH BETTER
        {
         //   radius = BALL_RADIUS_SMALL;
            width = 10;
            height = 10;
            energy_constant = BALL_ENERGY_CONSTANT_SMALL;
            imageID = ImageStore.IMAGE_BALL_SMALL;
            //imageID =  get corresponding image from the image store
        }
        else if (size == 2)
        {
        //    radius = BALL_RADIUS_MID;
            width = 17;
            height = 17;
            energy_constant = BALL_ENERGY_CONSTANT_MID;
            imageID = ImageStore.IMAGE_BALL_MID;

            //imageID =  get corresponding image from the image store
        }
        else if (size == 3)
        {
        //    radius = BALL_RADIUS_BIG;
            width = 25;
            height = 25;
            energy_constant = BALL_ENERGY_CONSTANT_BIG;
            imageID = ImageStore.IMAGE_BALL_BIG;

            //imageID =  get corresponding image from the image store
        }

        if(direction == BALL_SPLITTED_DIRECTION_LEFT)
        {
            this.size = size;
            Point p = new Point((-1)*SPLITTED_BALL_SPEED_X, SPLITTED_BALL_SPEED_Y);
            setDirection(p);
        }
        else if(direction == BALL_SPLITTED_DIRECTION_RIGHT)
        {
            this.size = size;
            Point p = new Point(SPLITTED_BALL_SPEED_X, SPLITTED_BALL_SPEED_Y);
            setDirection(p);
        }

    }

    public ArrayList<ArrayList> split()
    {
        ArrayList<ArrayList> container = new ArrayList<ArrayList>();
        ArrayList<GameObject> balls = new ArrayList<GameObject>();
        ArrayList<GameObject> items = new ArrayList<GameObject>();

        if(size == 1)
        {
            if(itemtoDrop != null) // drop the item
            {
                Item toAdd = itemtoDrop;
                toAdd.setDirection(0, GameObject.POWERUP_DROP_SPEED);
                toAdd.setCoordinates(this.coordinates);
                items.add(toAdd);
                itemtoDrop = null;
            }
            else if (itemtoDrop == null)
            {
                // do nothing, arraylists should be empty
            }
        }
        else if (size > 1  && size < 4)
        {
            Ball ballLeft = new Ball(this.size-1, BALL_SPLITTED_DIRECTION_LEFT,this.coordinates);
            Ball ballRight =  new Ball(this.size-1, BALL_SPLITTED_DIRECTION_RIGHT,this.coordinates);
            ballLeft.setCoordinates(getCoordinates().getX()-50, getCoordinates().getY());
            ballRight.setCoordinates(getCoordinates().getX()+50, getCoordinates().getY());


            balls.add(ballLeft); balls.add(ballRight);

            if(itemtoDrop != null)
            {
                int random = (int)(Math.random() * 3); // does it really work
                if (random == 0) // 1/3 probability it will drop the powerup
                {
                    Item toAdd = itemtoDrop;
                    toAdd.setDirection(0, GameObject.POWERUP_DROP_SPEED);
                    toAdd.setCoordinates(this.coordinates);
                    items.add(toAdd);
                    itemtoDrop = null;
                }
                else // 2/3 probability it will give it to one of its children
                {
                    if (random == 1)
                    {
                        ballLeft.setItemtoDrop(this.itemtoDrop);
                    }
                    else if (random == 2)
                    {
                        ballRight.setItemtoDrop(this.itemtoDrop);
                    }
                }
            }
            else if (itemtoDrop == null)
            {
                // do nothing, child balls are already created
            }
        }
        container.add(BALL_BALL_INDEX, balls);
        container.add(BALL_ITEM_INDEX, items);
        return container;
    }
/*
    @Override
    public boolean includes(double x, double y, double otherWidth, double otherHeight) // alter the algorithm with the margin in mind
    {
        Point coor = getCoordinates();
        double diffx = x - coor.getX();
        double diffy = y - coor.getY();

        if (diffx*diffx + diffy*diffy < radius*radius) // I really do not care about the floating point arithmetics inaccuracy
            return true;

        return false;
    }
*/
    @Override
    public void move() // after it moves, it adjusts its speed, to imitate the gravity force
    {

        coordinates.setLocation(coordinates.getX() + direction.getX() * UNIT_SPEED,
                coordinates.getY() + direction.getY() * UNIT_SPEED);

        setDirection();
    }

    /* how setDirection works is little strange,
    *  it uses the basic energy equation 1/2mv^2 + mgh = E
    *  then v = sqrt(k - gh)
    *  The fact that v(x) is constant changes pretty much nothing
    *  I assumed k grows with the ball size so that bigger balls bounce above the holly terra higher
    *  also notice that m is same for the all balls
    *  Then bigger balls move with more velocity than smaller balls
    *  which is the case in the original pang arcade game
    **/

    void setDirection() // I HAVE NO IDEA IF THIS WILL WORK
    {
        double velocityY = direction.getY();
        if (velocityY < 0.00000001 && velocityY > -0.00000001)
        {
            setDirection(direction.getX(), 3);
            return;
        }
        /*
        if (direction.getY() < 0) // if it has d(y) of zero
        {
            setDirection(direction.getX(), (-1)*direction.getY());
        }*/

        double locHeight = GameMap.GAME_DIMENSION.getHeight() - coordinates.getY() - height/2;
        double x = direction.getX();
        double y = 0; // because F you java
        double isItPositive = energy_constant - GameObject.G*locHeight - x*x;
        if ((isItPositive) > 0) // just double check
        {
                if(direction.getY() < 0) // then it goes upward
                    y = -Math.sqrt(energy_constant - GameObject.G*locHeight- x*x);
                else if(direction.getY() > 0)
                    y = Math.sqrt(energy_constant - GameObject.G*locHeight- x*x);
        }
        else
            y = Math.sqrt((-1)*(energy_constant - GameObject.G*locHeight- x*x)); // then it is slighly above the h

        setDirection(x, y);
    }

    void setItemtoDrop(Item item)
    {
        itemtoDrop = item;
    }

    public void bounce(int d)
    {
        if (d == GameObject.Y)
        {
            double newYSpeed = direction.getY() *(-1);
            setDirection(direction.getX(), newYSpeed);
        }
        else if (d == GameObject.X)
        {
            double newXSpeed = direction.getX()*(-1);
            setDirection(newXSpeed, direction.getY());
        }

        move();
        move();
        move();

    }

    public int getSize()
    {
        return size;
    }

    public void reverseDirection() {
        
    }
}
